﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.IO;

namespace SPSource
{
    public class SPSource
    {
        private string _designSiteURL = string.Empty;
        public string DesignSiteUrl
        {
            get { return _designSiteURL; }
            set
            {
                if (!value.EndsWith("/"))
                    value = value + "/";
                _designSiteURL = value;
            }
        }

        private DirectoryInfo _rootProjDir;
        public DirectoryInfo RootProjDir
        {
            get { return _rootProjDir; }
            set { _rootProjDir = value; }
        }

        private bool _overrideFeatureDirectoryCheck;
        public bool OverrideFeatureDirectoryCheck
        {
            get { return _overrideFeatureDirectoryCheck; }
            set { _overrideFeatureDirectoryCheck = value; }
        }

        public void Execute()
        {
            DirectoryInfo startDirectory = null;
            if (_overrideFeatureDirectoryCheck)
                startDirectory = RootProjDir;
            else
            {
                //NOTE: this is case insensitive on folder search - so checking both folder names from different tools
                DirectoryInfo[] wspbuilderdirs = RootProjDir.GetDirectories(Constants.FeatureDirectoryName, SearchOption.AllDirectories);
                DirectoryInfo[] spvisualdevdirs = RootProjDir.GetDirectories(Constants.SPVisualDevFeatureDirectoryName, SearchOption.AllDirectories);
                if (wspbuilderdirs.Length == 0 && spvisualdevdirs.Length == 0)
                    throw new ApplicationException("FEATURES folder does not exist in folder structure");

                DirectoryInfo[] dirs = (wspbuilderdirs.Length > 0 ? wspbuilderdirs : spvisualdevdirs);
                foreach (DirectoryInfo dir in dirs)
                {
                    //NOTE: only match on exact name match
                    if (dir.Name == Constants.FeatureDirectoryName)
                        startDirectory = dir;
                }
            }

            if (startDirectory != null)
            {
                FileInfo[] files = startDirectory.GetFiles("*" + Constants.SPSourceExtension, SearchOption.AllDirectories);
                ProcessFiles(files, startDirectory);
            }
        }

        private void ProcessFiles(FileInfo[] files, DirectoryInfo featureDirectory)
        {
            foreach (FileInfo file in files)
                ProcessFile(file, featureDirectory);
        }

        private void ProcessFile(FileInfo file, DirectoryInfo featureDirectory)
        {
            Utility.WriteMessage("Found .spsource file: " + file.FullName, file.Name);

            var spSourceFileInfo = new SPSourceFileInfo();
            spSourceFileInfo.DesignSiteUrl = this.DesignSiteUrl;
            spSourceFileInfo.SPSourceFileDirectoryInfo = file.Directory;
            spSourceFileInfo.SPSourceFileName = file.Name.ToLower();
            spSourceFileInfo.OverrideFeatureDirectoryCheck = _overrideFeatureDirectoryCheck;
            if (_overrideFeatureDirectoryCheck)
            {
                //if not in feature generate one
                spSourceFileInfo.FeatureId = Guid.NewGuid();
            }
            else
            {
                spSourceFileInfo.FeatureId = FeatureManager.GetFeatureIdFromFileLocation(file);
            }
            spSourceFileInfo.FeatureDirectory = featureDirectory;

            var spSourceFileProcessor = new SPSourceFileProcessor(spSourceFileInfo);

            var spSourceXmlDocument = new XmlDocument();
            spSourceXmlDocument.PreserveWhitespace = true;

            try
            {
                spSourceXmlDocument.Load(file.FullName);
            }
            catch (Exception ex)
            {
                Utility.WriteError(String.Format("The XML file is invalid located at {0}", file.FullName));
            }

            var nsmgr = new XmlNamespaceManager(spSourceXmlDocument.NameTable);
            foreach (XmlAttribute attr in spSourceXmlDocument.DocumentElement.Attributes)
            {
                if (attr.Name == "xmlns")
                {
                    nsmgr.AddNamespace("wss", attr.Value);
                    break;
                }
            }
            spSourceFileInfo.NamespaceManager = nsmgr;
            
            foreach (XmlNode element in spSourceXmlDocument.DocumentElement.ChildNodes)
            {
                var method = spSourceFileProcessor.GetType().GetMethod(element.Name);
                List<object> paramaters = new List<object>();
                paramaters.Add(element);
                if (method != null)
                    method.Invoke(spSourceFileProcessor, paramaters.ToArray());
            }
        }
    }
}
